{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "fd3eb704",
   "metadata": {},
   "source": [
    "# MariaDB\n",
    "\n",
    "\n",
    "In this tutorial, we'll see how to query MariaDB from Jupyter. Optionally, you can spin up a testing server.\n",
    "\n",
    "```{tip}\n",
    "If you encounter issues, feel free to join our [community](https://ploomber.io/community) and we'll be happy to help!\n",
    "```\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4727e0b9",
   "metadata": {},
   "source": [
    "## Pre-requisites\n",
    "\n",
    "To run this tutorial, you need to install the `mysqlclient` package.\n",
    "\n",
    "```{note}\n",
    "We highly recommend you that you install it using `conda`, since it'll also install `mysql-connector-c`; if you want to use `pip`, then you need to install `mysql-connector-c` and then `mysqlclient`.\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "ae033470",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Collecting package metadata (current_repodata.json): ...working... done\n",
      "Solving environment: ...working... done\n",
      "\n",
      "## Package Plan ##\n",
      "\n",
      "  environment location: /Users/eduardo/miniconda3/envs/jupysql\n",
      "\n",
      "  added / updated specs:\n",
      "    - mysqlclient\n",
      "\n",
      "\n",
      "The following NEW packages will be INSTALLED:\n",
      "\n",
      "  mysql-connector-c  pkgs/main/osx-arm64::mysql-connector-c-6.1.11-h4a942e0_1 \n",
      "  mysqlclient        pkgs/main/osx-arm64::mysqlclient-2.0.3-py310hc377ac9_1 \n",
      "\n",
      "\n",
      "Preparing transaction: ...working... done\n",
      "Verifying transaction: ...working... done\n",
      "Executing transaction: ...working... done\n",
      "\n",
      "Note: you may need to restart the kernel to use updated packages.\n"
     ]
    }
   ],
   "source": [
    "%conda install mysqlclient -c conda-forge --quiet"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dbf4706e",
   "metadata": {},
   "source": [
    "## Start MariaDB instance\n",
    "\n",
    "If you don't have a MariaDB Server running or you want to spin up one for testing, you can do it with the official [Docker image](https://hub.docker.com/_/mariadb).\n",
    "\n",
    "To start the server:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "f9c88366",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "c2a0a18f9c37285ffdb17b22d75a3a8ae789a93f58a59c9c1892a4f30f7bf9a2\n"
     ]
    }
   ],
   "source": [
    "%%bash\n",
    "docker run --detach --name mariadb \\\n",
    "    --env MARIADB_USER=user \\\n",
    "    --env MARIADB_PASSWORD=password \\\n",
    "    --env MARIADB_ROOT_PASSWORD=password \\\n",
    "    --env MARIADB_DATABASE=db \\\n",
    "    -p 3306:3306 mariadb:latest"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "eaae2079",
   "metadata": {},
   "source": [
    "Ensure that the container is running:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "ec326f31-6cac-4f97-a5f6-5538e694082b",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CONTAINER ID   IMAGE            COMMAND                  CREATED        STATUS                  PORTS                    NAMES\n",
      "c2a0a18f9c37   mariadb:latest   \"docker-entrypoint.s…\"   1 second ago   Up Less than a second   0.0.0.0:3306->3306/tcp   mariadb\n"
     ]
    }
   ],
   "source": [
    "%%bash\n",
    "docker ps"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9d74d2df",
   "metadata": {},
   "source": [
    "## Load sample data\n",
    "\n",
    "Now, let's fetch some sample data. We'll be using the [NYC taxi dataset](https://www.nyc.gov/site/tlc/about/tlc-trip-record-data.page):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "82b7d34f-aa22-4625-b2ff-cebcc70747da",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Note: you may need to restart the kernel to use updated packages.\n"
     ]
    }
   ],
   "source": [
    "%pip install pandas pyarrow --quiet"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "16b1bfed",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1369769, 19)"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import pandas as pd\n",
    "\n",
    "df = pd.read_parquet(\n",
    "    \"https://d37ci6vzurychx.cloudfront.net/trip-data/yellow_tripdata_2021-01.parquet\"\n",
    ")\n",
    "df.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f9ba5421",
   "metadata": {},
   "source": [
    "As you can see, this chunk of data contains ~1.4M rows, loading the data will take about a minute:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "a3402cdf",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "from sqlalchemy import create_engine\n",
    "\n",
    "engine = create_engine(\"mysql+mysqldb://user:password@127.0.0.1:3306/db\")\n",
    "df.to_sql(name=\"taxi\", con=engine, chunksize=100_000)\n",
    "engine.dispose()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c7f25de0",
   "metadata": {
    "user_expressions": []
   },
   "source": [
    "## Query\n",
    "\n",
    "```{note}\n",
    "`mysql` and `mysql+pymysql` connections (and perhaps others) don't read your client character set information from `.my.cnf.` You need to specify it in the connection string:\n",
    "\n",
    "~~~\n",
    "mysql+pymysql://scott:tiger@localhost/foo?charset=utf8\n",
    "~~~\n",
    "```\n",
    "\n",
    "\n",
    "Now, let's install JupySQL, authenticate and start querying the data!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "3df653d7",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Note: you may need to restart the kernel to use updated packages.\n"
     ]
    }
   ],
   "source": [
    "%pip install jupysql --quiet\n",
    "%load_ext sql\n",
    "%sql mysql+mysqldb://user:password@127.0.0.1:3306/db"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4e7beda3",
   "metadata": {},
   "source": [
    "```{important}\n",
    "If the cell above fails, you might have some missing packages. Message us on [Slack](https://ploomber.io/community) and we'll help you!\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "42d41200-2429-4f50-98c4-d974065f8070",
   "metadata": {},
   "source": [
    "List the tables in the database:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "3ff7c2d9-20b3-4214-bbd0-8043dd78aa67",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<table>\n",
       "    <thead>\n",
       "        <tr>\n",
       "            <th>Name</th>\n",
       "        </tr>\n",
       "    </thead>\n",
       "    <tbody>\n",
       "        <tr>\n",
       "            <td>taxi</td>\n",
       "        </tr>\n",
       "    </tbody>\n",
       "</table>"
      ],
      "text/plain": [
       "+------+\n",
       "| Name |\n",
       "+------+\n",
       "| taxi |\n",
       "+------+"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%sqlcmd tables"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "89b881b3-ec2f-4002-ba61-2cf3c9fe2ef2",
   "metadata": {},
   "source": [
    "List columns in the taxi table:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "547d41a8-2ea1-4152-a4da-653da9f4bcc9",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<table>\n",
       "    <thead>\n",
       "        <tr>\n",
       "            <th>name</th>\n",
       "            <th>type</th>\n",
       "            <th>default</th>\n",
       "            <th>comment</th>\n",
       "            <th>nullable</th>\n",
       "            <th>autoincrement</th>\n",
       "        </tr>\n",
       "    </thead>\n",
       "    <tbody>\n",
       "        <tr>\n",
       "            <td>index</td>\n",
       "            <td>BIGINT</td>\n",
       "            <td>None</td>\n",
       "            <td>None</td>\n",
       "            <td>True</td>\n",
       "            <td>False</td>\n",
       "        </tr>\n",
       "        <tr>\n",
       "            <td>VendorID</td>\n",
       "            <td>BIGINT</td>\n",
       "            <td>None</td>\n",
       "            <td>None</td>\n",
       "            <td>True</td>\n",
       "            <td>False</td>\n",
       "        </tr>\n",
       "        <tr>\n",
       "            <td>tpep_pickup_datetime</td>\n",
       "            <td>DATETIME</td>\n",
       "            <td>None</td>\n",
       "            <td>None</td>\n",
       "            <td>True</td>\n",
       "            <td></td>\n",
       "        </tr>\n",
       "        <tr>\n",
       "            <td>tpep_dropoff_datetime</td>\n",
       "            <td>DATETIME</td>\n",
       "            <td>None</td>\n",
       "            <td>None</td>\n",
       "            <td>True</td>\n",
       "            <td></td>\n",
       "        </tr>\n",
       "        <tr>\n",
       "            <td>passenger_count</td>\n",
       "            <td>DOUBLE</td>\n",
       "            <td>None</td>\n",
       "            <td>None</td>\n",
       "            <td>True</td>\n",
       "            <td></td>\n",
       "        </tr>\n",
       "        <tr>\n",
       "            <td>trip_distance</td>\n",
       "            <td>DOUBLE</td>\n",
       "            <td>None</td>\n",
       "            <td>None</td>\n",
       "            <td>True</td>\n",
       "            <td></td>\n",
       "        </tr>\n",
       "        <tr>\n",
       "            <td>RatecodeID</td>\n",
       "            <td>DOUBLE</td>\n",
       "            <td>None</td>\n",
       "            <td>None</td>\n",
       "            <td>True</td>\n",
       "            <td></td>\n",
       "        </tr>\n",
       "        <tr>\n",
       "            <td>store_and_fwd_flag</td>\n",
       "            <td>TEXT</td>\n",
       "            <td>None</td>\n",
       "            <td>None</td>\n",
       "            <td>True</td>\n",
       "            <td></td>\n",
       "        </tr>\n",
       "        <tr>\n",
       "            <td>PULocationID</td>\n",
       "            <td>BIGINT</td>\n",
       "            <td>None</td>\n",
       "            <td>None</td>\n",
       "            <td>True</td>\n",
       "            <td>False</td>\n",
       "        </tr>\n",
       "        <tr>\n",
       "            <td>DOLocationID</td>\n",
       "            <td>BIGINT</td>\n",
       "            <td>None</td>\n",
       "            <td>None</td>\n",
       "            <td>True</td>\n",
       "            <td>False</td>\n",
       "        </tr>\n",
       "        <tr>\n",
       "            <td>payment_type</td>\n",
       "            <td>BIGINT</td>\n",
       "            <td>None</td>\n",
       "            <td>None</td>\n",
       "            <td>True</td>\n",
       "            <td>False</td>\n",
       "        </tr>\n",
       "        <tr>\n",
       "            <td>fare_amount</td>\n",
       "            <td>DOUBLE</td>\n",
       "            <td>None</td>\n",
       "            <td>None</td>\n",
       "            <td>True</td>\n",
       "            <td></td>\n",
       "        </tr>\n",
       "        <tr>\n",
       "            <td>extra</td>\n",
       "            <td>DOUBLE</td>\n",
       "            <td>None</td>\n",
       "            <td>None</td>\n",
       "            <td>True</td>\n",
       "            <td></td>\n",
       "        </tr>\n",
       "        <tr>\n",
       "            <td>mta_tax</td>\n",
       "            <td>DOUBLE</td>\n",
       "            <td>None</td>\n",
       "            <td>None</td>\n",
       "            <td>True</td>\n",
       "            <td></td>\n",
       "        </tr>\n",
       "        <tr>\n",
       "            <td>tip_amount</td>\n",
       "            <td>DOUBLE</td>\n",
       "            <td>None</td>\n",
       "            <td>None</td>\n",
       "            <td>True</td>\n",
       "            <td></td>\n",
       "        </tr>\n",
       "        <tr>\n",
       "            <td>tolls_amount</td>\n",
       "            <td>DOUBLE</td>\n",
       "            <td>None</td>\n",
       "            <td>None</td>\n",
       "            <td>True</td>\n",
       "            <td></td>\n",
       "        </tr>\n",
       "        <tr>\n",
       "            <td>improvement_surcharge</td>\n",
       "            <td>DOUBLE</td>\n",
       "            <td>None</td>\n",
       "            <td>None</td>\n",
       "            <td>True</td>\n",
       "            <td></td>\n",
       "        </tr>\n",
       "        <tr>\n",
       "            <td>total_amount</td>\n",
       "            <td>DOUBLE</td>\n",
       "            <td>None</td>\n",
       "            <td>None</td>\n",
       "            <td>True</td>\n",
       "            <td></td>\n",
       "        </tr>\n",
       "        <tr>\n",
       "            <td>congestion_surcharge</td>\n",
       "            <td>DOUBLE</td>\n",
       "            <td>None</td>\n",
       "            <td>None</td>\n",
       "            <td>True</td>\n",
       "            <td></td>\n",
       "        </tr>\n",
       "        <tr>\n",
       "            <td>airport_fee</td>\n",
       "            <td>DOUBLE</td>\n",
       "            <td>None</td>\n",
       "            <td>None</td>\n",
       "            <td>True</td>\n",
       "            <td></td>\n",
       "        </tr>\n",
       "    </tbody>\n",
       "</table>"
      ],
      "text/plain": [
       "+-----------------------+----------+---------+---------+----------+---------------+\n",
       "|          name         |   type   | default | comment | nullable | autoincrement |\n",
       "+-----------------------+----------+---------+---------+----------+---------------+\n",
       "|         index         |  BIGINT  |   None  |   None  |   True   |     False     |\n",
       "|        VendorID       |  BIGINT  |   None  |   None  |   True   |     False     |\n",
       "|  tpep_pickup_datetime | DATETIME |   None  |   None  |   True   |               |\n",
       "| tpep_dropoff_datetime | DATETIME |   None  |   None  |   True   |               |\n",
       "|    passenger_count    |  DOUBLE  |   None  |   None  |   True   |               |\n",
       "|     trip_distance     |  DOUBLE  |   None  |   None  |   True   |               |\n",
       "|       RatecodeID      |  DOUBLE  |   None  |   None  |   True   |               |\n",
       "|   store_and_fwd_flag  |   TEXT   |   None  |   None  |   True   |               |\n",
       "|      PULocationID     |  BIGINT  |   None  |   None  |   True   |     False     |\n",
       "|      DOLocationID     |  BIGINT  |   None  |   None  |   True   |     False     |\n",
       "|      payment_type     |  BIGINT  |   None  |   None  |   True   |     False     |\n",
       "|      fare_amount      |  DOUBLE  |   None  |   None  |   True   |               |\n",
       "|         extra         |  DOUBLE  |   None  |   None  |   True   |               |\n",
       "|        mta_tax        |  DOUBLE  |   None  |   None  |   True   |               |\n",
       "|       tip_amount      |  DOUBLE  |   None  |   None  |   True   |               |\n",
       "|      tolls_amount     |  DOUBLE  |   None  |   None  |   True   |               |\n",
       "| improvement_surcharge |  DOUBLE  |   None  |   None  |   True   |               |\n",
       "|      total_amount     |  DOUBLE  |   None  |   None  |   True   |               |\n",
       "|  congestion_surcharge |  DOUBLE  |   None  |   None  |   True   |               |\n",
       "|      airport_fee      |  DOUBLE  |   None  |   None  |   True   |               |\n",
       "+-----------------------+----------+---------+---------+----------+---------------+"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%sqlcmd columns --table taxi"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "490e8aae-2aa1-4c19-bb2a-141849b03c2d",
   "metadata": {},
   "source": [
    "Query our data:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "84902d46",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "*  mysql+mysqldb://user:***@127.0.0.1:3306/db\n",
      "1 rows affected.\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<table>\n",
       "    <thead>\n",
       "        <tr>\n",
       "            <th>COUNT(*)</th>\n",
       "        </tr>\n",
       "    </thead>\n",
       "    <tbody>\n",
       "        <tr>\n",
       "            <td>1369769</td>\n",
       "        </tr>\n",
       "    </tbody>\n",
       "</table>"
      ],
      "text/plain": [
       "[(1369769,)]"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%%sql\n",
    "SELECT COUNT(*) FROM taxi"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4e838b37-e679-4ffa-98b7-1dc80e909a41",
   "metadata": {},
   "source": [
    "## Parametrize queries"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "ff575b33-c27c-4c58-8f31-17b930454191",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "threshold = 10"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "58106d30-790d-4c8a-88da-86dd0b0c12bc",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "*  mysql+mysqldb://user:***@127.0.0.1:3306/db\n",
      "1 rows affected.\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<table>\n",
       "    <thead>\n",
       "        <tr>\n",
       "            <th>COUNT(*)</th>\n",
       "        </tr>\n",
       "    </thead>\n",
       "    <tbody>\n",
       "        <tr>\n",
       "            <td>1297415</td>\n",
       "        </tr>\n",
       "    </tbody>\n",
       "</table>"
      ],
      "text/plain": [
       "[(1297415,)]"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%%sql\n",
    "SELECT COUNT(*) FROM taxi\n",
    "WHERE trip_distance < {{threshold}}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "b820944c-0016-484a-a23f-42f4290ccce8",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "threshold = 0.5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "7fb73771-2251-4ed4-95ca-8f89ef0131b6",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "*  mysql+mysqldb://user:***@127.0.0.1:3306/db\n",
      "1 rows affected.\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<table>\n",
       "    <thead>\n",
       "        <tr>\n",
       "            <th>COUNT(*)</th>\n",
       "        </tr>\n",
       "    </thead>\n",
       "    <tbody>\n",
       "        <tr>\n",
       "            <td>73849</td>\n",
       "        </tr>\n",
       "    </tbody>\n",
       "</table>"
      ],
      "text/plain": [
       "[(73849,)]"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%%sql\n",
    "SELECT COUNT(*) FROM taxi\n",
    "WHERE trip_distance < {{threshold}}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cffcaf73-c2f3-4cc6-b777-7a2784c743e9",
   "metadata": {},
   "source": [
    "## CTEs\n",
    "\n",
    "You can break down queries into multiple cells, JupySQL will build a CTE for you:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "7ec71402",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "*  mysql+mysqldb://user:***@127.0.0.1:3306/db\n",
      "Skipping execution...\n"
     ]
    }
   ],
   "source": [
    "%%sql --save many_passengers --no-execute\n",
    "SELECT *\n",
    "FROM taxi\n",
    "WHERE passenger_count > 3\n",
    "-- remove top 1% outliers for better visualization\n",
    "AND trip_distance < 18.93"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "e5195ed0-d354-4565-937e-fb6be55e4353",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "*  mysql+mysqldb://user:***@127.0.0.1:3306/db\n",
      "1 rows affected.\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<table>\n",
       "    <thead>\n",
       "        <tr>\n",
       "            <th>MIN(trip_distance)</th>\n",
       "            <th>AVG(trip_distance)</th>\n",
       "            <th>MAX(trip_distance)</th>\n",
       "        </tr>\n",
       "    </thead>\n",
       "    <tbody>\n",
       "        <tr>\n",
       "            <td>0.0</td>\n",
       "            <td>2.5010889812889836</td>\n",
       "            <td>18.92</td>\n",
       "        </tr>\n",
       "    </tbody>\n",
       "</table>"
      ],
      "text/plain": [
       "[(0.0, 2.5010889812889836, 18.92)]"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%%sql --save trip_stats --with many_passengers\n",
    "SELECT MIN(trip_distance), AVG(trip_distance), MAX(trip_distance)\n",
    "FROM many_passengers"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4e9882ea-2769-4a12-abc3-1a2bf95bfdc0",
   "metadata": {},
   "source": [
    "This is what JupySQL executes:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "636803f1-7c40-4695-b950-5604dad98c33",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WITH `many_passengers` AS (\n",
      "SELECT *\n",
      "FROM taxi\n",
      "WHERE passenger_count > 3\n",
      "-- remove top 1% outliers for better visualization\n",
      "AND trip_distance < 18.93)\n",
      "SELECT MIN(trip_distance), AVG(trip_distance), MAX(trip_distance)\n",
      "FROM many_passengers\n"
     ]
    }
   ],
   "source": [
    "query = %sqlcmd snippets trip_stats\n",
    "print(query)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8599517c-10a3-47f4-9a5d-a4d45712503a",
   "metadata": {},
   "source": [
    "## Plotting"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "3c7845eb-59f4-495f-a3a3-d9ff150e323e",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<AxesSubplot: title={'center': \"'trip_distance' from 'many_passengers'\"}, xlabel='trip_distance', ylabel='Count'>"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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fPiwbDabRo4cqZdffllff/21du3apYEDByogIMD8ZuKtt96qbt26aciQIdq8ebPWr1+v2NhY9e3bVwEBAZKkhx56SC4uLho8eLCSkpI0f/58vfnmmxo1apTZx1NPPaWlS5dq6tSp2rdvn+Li4rR161bFxsZe7x8JAACoQCqX5sa3bt2qO++803yeG36io6MVHx+v559/XmfPntXQoUOVlpam9u3ba+nSpXJzczOXmTdvnmJjY9WlSxc5OTmpd+/eeuutt8z5drtdy5cvV0xMjFq2bKmaNWtq3LhxDvfaateunT7++GP985//1P/7f/9P9evX16JFi9SoUaPr8FMAAAAVVZm5j1Z5x320AAAof27Y+2gBAACUdwQtAAAAixC0AAAALELQAgAAsAhBCwAAwCIELQAAAIsQtAAAACxC0AIAALAIQQsAAMAiBC0AAACLELQAAAAsQtACAACwCEELAADAIgQtAAAAixC0AAAALELQAgAAsAhBCwAAwCIELQAAAIsQtAAAACxC0AIAALAIQQsAAMAiBC0AAACLELQAAAAsQtACAACwCEELAADAIgQtAAAAixC0AAAALELQAgAAsAhBCwAAwCIELQAAAIsQtAAAACxC0AIAALAIQQsAAMAiBC0AAACLELQAAAAsQtACAACwCEELAADAIgQtAAAAixC0AAAALELQAgAAsEjl0m4AJSd4zJIys52Dr0Zeh04AACjbOKIFAABgEYIWAACARQhaAAAAFiFoAQAAWISgBQAAYJEyHbSys7P14osvKiQkRO7u7qpbt65eeuklGYZh1hiGoXHjxqlWrVpyd3dXeHi4Dhw44LCekydPqn///vLy8pK3t7cGDx6sM2fOONTs3LlTHTp0kJubmwIDAzV58uTrMkYAAFBxlemg9dprr2nmzJl6++23tXfvXr322muaPHmypk+fbtZMnjxZb731lmbNmqVNmzbJw8NDERERunDhglnTv39/JSUlKSEhQYsXL9a6des0dOhQc35GRoa6du2qoKAgbdu2TVOmTFFcXJzee++96zpeAABQsdiMyw8PlTF33323/Pz89OGHH5rTevfuLXd3d82dO1eGYSggIEDPPPOMnn32WUlSenq6/Pz8FB8fr759+2rv3r0KDQ3Vli1b1KpVK0nS0qVL1aNHDx09elQBAQGaOXOmXnjhBaWkpMjFxUWS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AFiEoAUAAGARghYAAIBFCFoAyry4uDg1a9bM0m107txZI0eONJ8HBwdr2rRplm4TQMVH0AJQaq4MNwV59tln8/z9R6tt2bJFQ4cOLVQtoQxAQSqXdgMAUBDDMJSdnS1PT095enpe1237+Phc1+0BqJg4ogWgVAwaNEhr167Vm2++KZvNJpvNpvj4eNlsNn333Xdq2bKlXF1d9f333+c5dTho0CBFRUVpwoQJ8vHxkZeXl5544gllZmYWattnz57VwIED5enpqVq1amnq1Kl5ai4/SmUYhuLi4lSnTh25uroqICBAI0aMkPTXUblDhw7p6aefNschSSdOnFC/fv100003qUqVKmrcuLE++eQTh2107txZI0aM0PPPP6/q1avL399fcXFxDjVpaWl6/PHH5efnJzc3NzVq1EiLFy8253///ffq0KGD3N3dFRgYqBEjRujs2bOF+jkAsB5BC0CpePPNNxUWFqYhQ4bo999/1++//67AwEBJ0pgxY/Tqq69q7969atKkSb7Lr1y5Unv37tWaNWv0ySefaMGCBZowYUKhtv3cc89p7dq1+uqrr7R8+XKtWbNG27dvL7D+yy+/1BtvvKF3331XBw4c0KJFi9S4cWNJ0oIFC1S7dm1NnDjRHIckXbhwQS1bttSSJUu0e/duDR06VAMGDNDmzZsd1j1nzhx5eHho06ZNmjx5siZOnKiEhARJUk5Ojrp3767169dr7ty52rNnj1599VVVqlRJkvTLL7+oW7du6t27t3bu3Kn58+fr+++/V2xsbKF+DgCug+L+pWwA+Ls6depkPPXUU+bz1atXG5KMRYsWOdSNHz/eaNq0qfk8OjraqF69unH27Flz2syZMw1PT08jOzv7qts8ffq04eLiYnz22WfmtBMnThju7u4OvQQFBRlvvPGGYRiGMXXqVOOWW24xMjMz813n5bVXExkZaTzzzDPm806dOhnt27d3qLn99tuN0aNHG4ZhGMuWLTOcnJyM/fv357u+wYMHG0OHDnWY9r///c9wcnIyzp8/f81+AFiPI1oAypxWrVpds6Zp06aqUqWK+TwsLExnzpzRkSNHrrrcL7/8oszMTLVp08acVr16dTVo0KDAZR544AGdP39eN998s4YMGaKFCxfq0qVLV91Odna2XnrpJTVu3FjVq1eXp6enli1bpsOHDzvUXXnErlatWjp+/LgkaceOHapdu7ZuueWWfLfx448/Kj4+3ryGzdPTUxEREcrJyVFycvJV+wNwfXAxPIAyx8PDo7RbcBAYGKj9+/drxYoVSkhI0JNPPqkpU6Zo7dq1cnZ2zneZKVOm6M0339S0adPUuHFjeXh4aOTIkXmuI7tyeZvNppycHEmSu7v7Vfs6c+aMHn/8cfN6scvVqVOnKEMEYBGCFoBS4+Liouzs7GIt++OPP+r8+fNmGNm4caM8PT3N67wKUrduXTk7O2vTpk1mGDl16pR++uknderUqcDl3N3d1bNnT/Xs2VMxMTFq2LChdu3apRYtWuQ7jvXr1+vee+/Vww8/LOmv661++uknhYaGFnqMTZo00dGjR/XTTz/le1SrRYsW2rNnj+rVq1fodQK4vjh1CKDUBAcHa9OmTTp48KD+/PNP80hOYWRmZmrw4MHas2ePvv32W40fP16xsbFycrr6f2uenp4aPHiwnnvuOa1atUq7d+/WoEGDrrpcfHy8PvzwQ+3evVu//vqr5s6dK3d3dwUFBZnjWLdunX777Tf9+eefkqT69esrISFBGzZs0N69e/X4448rNTW10OOTpE6dOqljx47q3bu3EhISlJycrO+++05Lly6VJI0ePVobNmxQbGysduzYoQMHDuirr77iYnigDCFoASg1zz77rCpVqqTQ0FD5+PjkuX7parp06aL69eurY8eOevDBB3XPPffkuTVCQaZMmaIOHTqoZ8+eCg8PV/v27dWyZcsC6729vfX+++/rjjvuUJMmTbRixQp98803qlGjhiRp4sSJOnjwoOrWrWvef+uf//ynWrRooYiICHXu3Fn+/v6Kiooq9Phyffnll7r99tvVr18/hYaG6vnnnzePnjVp0kRr167VTz/9pA4dOqh58+YaN26cAgICirwdANawGYZhlHYTAFAUgwYNUlpamhYtWlTarQDAVXFECwAAwCIELQAVyuHDhx1ud3DloyinJwHg7+LUIYAK5dKlSzp48GCB84ODg1W5Ml+4BnB9ELQAAAAswqlDAAAAixC0AAAALELQAgAAsAhBCwAAwCIELQAAAIsQtAAAACxC0AIAALAIQQsAAMAi/x/xuOIVWacZFAAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%sqlplot histogram --table many_passengers --column trip_distance --with many_passengers"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3544f41d",
   "metadata": {},
   "source": [
    "## Clean up\n",
    "\n",
    "To stop and remove the container:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "6d408cc0",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CONTAINER ID   IMAGE            COMMAND                  CREATED         STATUS         PORTS                    NAMES\n",
      "c2a0a18f9c37   mariadb:latest   \"docker-entrypoint.s…\"   2 minutes ago   Up 2 minutes   0.0.0.0:3306->3306/tcp   mariadb\n"
     ]
    }
   ],
   "source": [
    "%%bash\n",
    "docker container ls"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "42c37efd-1666-42dd-a38c-1944860b9c39",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "mariadb\n"
     ]
    }
   ],
   "source": [
    "%%bash\n",
    "docker container stop mariadb"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "6c9bce10",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "mariadb\n"
     ]
    }
   ],
   "source": [
    "%%bash\n",
    "docker container rm mariadb"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "17d42e97-9be7-43a8-916a-56dea1ca3dda",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES\n"
     ]
    }
   ],
   "source": [
    "%%bash\n",
    "docker container ls"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.11"
  },
  "myst": {
   "html_meta": {
    "description lang=en": "Query a MariaDB database from Jupyter via JupySQL",
    "keywords": "jupyter, sql, jupysql, mysql",
    "property=og:locale": "en_US"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
